package controllers

import java.io.File
import java.nio.file.Files

import config.{Global, MyFile, MyRow}
import dao.GenomeDao
import javax.inject.Inject
import org.apache.commons.io.FileUtils
import play.api.data.Form
import play.api.data.Forms._
import play.api.libs.json.Json
import play.api.mvc._
import utils.ExecCommand

import scala.concurrent.ExecutionContext

class SearchController @Inject()(genomeDao: GenomeDao,
                                 cc: ControllerComponents )
                                (implicit exec: ExecutionContext) extends AbstractController(cc) with MyFile with MyRow{


  def searchPage: Action[AnyContent] = Action {implicit request=>
    Ok(views.html.search.searchPage())
  }

  def getChr(species: String) = Action { implicit request =>
    Ok(Json.toJson(s"${Global.path}/blastData/${species}_chr.txt".readLines.sorted))
  }


  def getSearchData(formId: String): Action[AnyContent] = Action.async { implicit request =>
    formId match {
      case "geneIdForm" => searchByGeneId
      case "rangeForm" => searchByRange
    }
  }

  case class SearchData(species: String, ids: String)

  val SearchForm = Form(
    mapping(
      "species" -> text,
      "ids" -> text
    )(SearchData.apply)(SearchData.unapply)
  )

  def searchByGeneId(implicit request: Request[AnyContent]) = {
    val data = SearchForm.bindFromRequest.get
    genomeDao.getByGeneIds(data.ids.trim.split(",").map(_.trim), data.species).map { x =>
      val json = x.map(_.getMapByT())
      Ok(Json.toJson(json))
    }
  }

  case class RangeData(species: String, chr: String, start: Int, end: Int)

  val RangeForm = Form(
    mapping(
      "species" -> text,
      "chr" -> text,
      "start" -> number,
      "end" -> number
    )(RangeData.apply)(RangeData.unapply)
  )

  def searchByRange(implicit request: Request[AnyContent]) = {
    val data = RangeForm.bindFromRequest.get
    genomeDao.getByRange(data.species, data.chr, data.start, data.end).map { x =>
      val json = x.map(_.getMapByT())
      Ok(Json.toJson(json))
    }
  }


  def seqFetchPage = Action { implicit request =>
    Ok(views.html.search.seqFetchPage())
  }

  case class SeqFetchData(species: String, region: String)

  val SeqFetchForm = Form(
    mapping(
      "species" -> text,
      "region" -> text
    )(SeqFetchData.apply)(SeqFetchData.unapply)
  )

  def seqFetch(formId: String) = Action { implicit request =>
    val tmpDir = Files.createTempDirectory("tmpDir").toString
    val outFile = new File(tmpDir, "data.txt")
    val execCommand = new ExecCommand

    val command = formId match {
      case "regionForm" =>
        val data = SeqFetchForm.bindFromRequest.get
        s"${Global.samtools} faidx ${Global.path}/blastData/genome/genome.fa ${data.region}"
      case "rangeForm" =>
        val data = RangeForm.bindFromRequest.get
        s"${Global.samtools} faidx ${Global.path}/blastData/genome/genome.fa ${data.chr}:${data.start}-${data.end}"
    }
    execCommand.execot(command, outFile, tmpDir)
    if (execCommand.isSuccess) {
      val dataStr = FileUtils.readFileToString(outFile)
      tmpDir.delete
      Ok(Json.obj("valid" -> "true", "fasta" -> dataStr.replaceAll("\n", "<br/>")))
    } else {
      tmpDir.delete
      Ok(Json.obj("valid" -> "false", "msg" -> execCommand.getErrStr))
    }
  }



}
